package com.nova.android.tvlauncher.ui.view

import android.animation.ArgbEvaluator
import android.animation.TimeInterpolator
import android.animation.ValueAnimator
import android.content.Context
import android.graphics.Color
import android.graphics.Rect
import android.graphics.drawable.Drawable
import android.graphics.drawable.GradientDrawable
import android.util.AttributeSet
import android.view.animation.DecelerateInterpolator
import androidx.appcompat.widget.AppCompatImageView
import androidx.core.content.withStyledAttributes
import com.nova.android.tvlauncher.R

class FocusImageView @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyle: Int = 0
) : AppCompatImageView(context, attrs, defStyle) {

    private var focusColor: Int = Color.BLUE
    private var normalColor: Int = Color.TRANSPARENT
    private var focusedImage: Drawable? = null
    private var normalImage: Drawable? = null
    private var backgroundDrawable: GradientDrawable? = null
    private var scaleFactor: Float = 1.15f
    private var animationDuration: Long = 300
    private var interpolator: TimeInterpolator = DecelerateInterpolator()

    init {
        context.withStyledAttributes(attrs, R.styleable.FocusImageView) {
            focusColor = getColor(R.styleable.FocusImageView_focusColor, Color.BLUE)
            normalColor = getColor(R.styleable.FocusImageView_normalColor, Color.TRANSPARENT)
            focusedImage = getDrawable(R.styleable.FocusImageView_focusedSrc)
            scaleFactor = getFloat(R.styleable.FocusImageView_scaleFactor, 1.15f)
            animationDuration = getInt(R.styleable.FocusImageView_animationDuration, 300).toLong()
        }

        // 默认图为空时自动使用初始 drawable
        normalImage = drawable ?: normalImage

        scaleX = 1f
        scaleY = 1f
        isFocusable = true
        isFocusableInTouchMode = true
        updateFocusState(isFocused, false)
    }

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        if (w > 0 && h > 0) {
            backgroundDrawable = createCircularDrawable(isFocused, w, h)
            background = backgroundDrawable
            // 立即刷新当前颜色，避免初始状态颜色不同步
            backgroundDrawable?.setColor(if (isFocused) focusColor else normalColor)
        }
    }

    private fun createCircularDrawable(isFocused: Boolean, width: Int, height: Int): GradientDrawable {
        return GradientDrawable().apply {
            shape = GradientDrawable.OVAL
            setColor(if (isFocused) focusColor else normalColor)
            setSize(width, height)
        }
    }

    override fun onFocusChanged(focused: Boolean, direction: Int, previouslyFocusedRect: Rect?) {
        super.onFocusChanged(focused, direction, previouslyFocusedRect)
        updateFocusState(focused, true)
    }

    override fun setSelected(selected: Boolean) {
        super.setSelected(selected)
        updateFocusState(selected, true)
    }

    private fun updateFocusState(focused: Boolean, withAnimation: Boolean) {
        if (withAnimation) {
            animateBackgroundColor(focused)
        } else {
            backgroundDrawable?.setColor(if (focused) focusColor else normalColor)
        }

        val targetDrawable = if (focused) focusedImage ?: normalImage else normalImage
        if (drawable != targetDrawable) {
            setImageDrawable(null)
            setImageDrawable(targetDrawable)
        }

        val scale = if (focused) scaleFactor else 1f
        if (withAnimation) {
            animate()
                .scaleX(scale)
                .scaleY(scale)
                .setDuration(animationDuration)
                .setInterpolator(interpolator)
                .start()
        } else {
            scaleX = scale
            scaleY = scale
        }
    }

    private fun animateBackgroundColor(focused: Boolean) {
        val startColor = if (focused) normalColor else focusColor
        val endColor = if (focused) focusColor else normalColor
        ValueAnimator.ofObject(ArgbEvaluator(), startColor, endColor).apply {
            duration = animationDuration
            addUpdateListener { animator ->
                backgroundDrawable?.setColor(animator.animatedValue as Int)
            }
            start()
        }
    }

    fun setFocusedImage(image: Drawable) {
        focusedImage = image
        if (isFocused) {
            setImageDrawable(focusedImage)
        }
    }

    fun setNormalImage(image: Drawable) {
        normalImage = image
        if (!isFocused) {
            setImageDrawable(normalImage)
        }
    }

    fun setFocusColor(color: Int) {
        focusColor = color
        if (isFocused) {
            backgroundDrawable?.setColor(focusColor)
            invalidate()
        }
    }

    fun setNormalColor(color: Int) {
        normalColor = color
        if (!isFocused) {
            backgroundDrawable?.setColor(normalColor)
            invalidate()
        }
    }

    fun setScaleFactor(factor: Float) {
        scaleFactor = factor
        if (isFocused) {
            animate()
                .scaleX(scaleFactor)
                .scaleY(scaleFactor)
                .setDuration(animationDuration)
                .setInterpolator(interpolator)
                .start()
        }
    }

    fun setAnimationDuration(duration: Long) {
        animationDuration = duration
    }

    fun setInterpolator(customInterpolator: TimeInterpolator) {
        interpolator = customInterpolator
    }
}
